---
title: sdk/router
description: The RedwoodSDK router
next: false
---

RedwoodSDK's router is a lightweight server-side router that's designed to work with `defineApp` from `rwsdk/worker`.

## `route`

The `route` function is used to define a route.

```ts
import { route } from "rwsdk/router";

route("/", () => new Response("Hello, World!"));
```

### Method-Based Routing

The `route` function also accepts a `MethodHandlers` object to handle different HTTP methods on the same path:

```ts
route("/api/users", {
  get: () => new Response(JSON.stringify(users)),
  post: () => new Response("Created", { status: 201 }),
  delete: () => new Response("Deleted", { status: 204 }),
});
```

Method handlers can also be arrays of functions for route-specific middleware:

```ts
route("/api/users", {
  get: [isAuthenticated, getUsersHandler],
  post: [isAuthenticated, validateUser, createUserHandler],
});
```

**Type signature**:

```ts
type MethodHandlers = {
  delete?: RouteHandler;
  get?: RouteHandler;
  head?: RouteHandler;
  patch?: RouteHandler;
  post?: RouteHandler;
  put?: RouteHandler;
  config?: {
    disable405?: true;
    disableOptions?: true;
  };
  custom?: {
    [method: string]: RouteHandler;
  };
};
```

**Custom methods**: For non-standard HTTP methods (e.g., WebDAV):

```ts
route("/api/search", {
  custom: {
    report: () => new Response("Report data"),
  },
});
```

**Default behavior**:

- OPTIONS requests return `204 No Content` with `Allow` header
- Unsupported methods return `405 Method Not Allowed` with `Allow` header
- Use `config.disableOptions` or `config.disable405` to opt out

## `prefix`

The `prefix` function is used to modify the matched string of a group of routes, by adding a prefix to the matched string. This essentially allows you to group related functionality into a seperate file, import those routes and place it into your `defineApp` function.

```ts title="app/pages/user/routes.ts"
import { route } from "rwsdk/router";

import { LoginPage } from "./LoginPage";

export const routes = [
  route("/login", LoginPage),
  route("/logout", () => {
    /* handle logout*/
  }),
];
```

```ts title="worker.ts"
import { prefix } from "rwsdk/router";

import { routes as userRoutes } from "@/app/pages/user/routes";

defineApp([prefix("/user", userRoutes)]);

---
This will match `/user/login` and `/user/logout`
---
```

## render

The `render` function is used to statically render the contents of a JSX element. It cannot contain any dynamic content. Use this to control the output of your HTML.

### Options

The `render` function accepts an optional third parameter with the following options:

- **`rscPayload`** (boolean, default: `true`) - Toggle the RSC payload that's appended to the Document. Disabling this will mean that interactivity can no longer work. Your document should not include any client side initialization.

- **`ssr`** (boolean, default: `true`) - Enable or disable server-side rendering beyond the 'use client' boundary on these routes. When disabled, 'use client' components will render only on the client. This is useful for client components which only work in a browser environment. NOTE: disabling `ssr` requires `rscPayload` to be enabled.

```tsx
import { render } from "rwsdk/router";

import { ReactDocument } from "@/app/Document";
import { StaticDocument } from "@/app/Document";

import { routes as appRoutes } from "@/app/pages/app/routes";
import { routes as docsRoutes } from "@/app/pages/docs/routes";
import { routes as spaRoutes } from "@/app/pages/spa/routes";

export default defineApp([
  // Default: SSR enabled with RSC payload
  render(ReactDocument, [prefix("/app", appRoutes)]),

  // Static rendering: SSR enabled, RSC payload disabled
  render(StaticDocument, [prefix("/docs", docsRoutes)], { rscPayload: false }),

  // Client-side only: SSR disabled, RSC payload enabled
  render(ReactDocument, [prefix("/spa", spaRoutes)], { ssr: false }),
]);
```

---

## Important Notes

**HEAD Requests**: Unlike Express.js, RedwoodSDK does not automatically map HEAD requests to GET handlers. You must explicitly define a HEAD handler if you want to support HEAD requests.

```ts
route("/api/users", {
  get: getHandler,
  head: getHandler, // Explicitly provide HEAD handler
});
```
